/* eslint-disable */
/**
 * Emulate touch event
 * Source：https://github.com/hammerjs/touchemulator
 */

var eventTarget;
var supportTouch = "ontouchstart" in window;

// polyfills
if (!document.createTouch) {
	document.createTouch = function (
		view,
		target,
		identifier,
		pageX,
		pageY,
		screenX,
		screenY
	) {
		// auto set
		return new Touch(
			target,
			identifier,
			{
				pageX: pageX,
				pageY: pageY,
				screenX: screenX,
				screenY: screenY,
				clientX: pageX - window.pageXOffset,
				clientY: pageY - window.pageYOffset,
			},
			0,
			0
		);
	};
}

if (!document.createTouchList) {
	document.createTouchList = function () {
		var touchList = TouchList();
		for (var i = 0; i < arguments.length; i++) {
			touchList[i] = arguments[i];
		}
		touchList.length = arguments.length;
		return touchList;
	};
}

/**
 * create an touch point
 * @constructor
 * @param target
 * @param identifier
 * @param pos
 * @param deltaX
 * @param deltaY
 * @returns {Object} touchPoint
 */

var Touch = function Touch(target, identifier, pos, deltaX, deltaY) {
	deltaX = deltaX || 0;
	deltaY = deltaY || 0;

	this.identifier = identifier;
	this.target = target;
	this.clientX = pos.clientX + deltaX;
	this.clientY = pos.clientY + deltaY;
	this.screenX = pos.screenX + deltaX;
	this.screenY = pos.screenY + deltaY;
	this.pageX = pos.pageX + deltaX;
	this.pageY = pos.pageY + deltaY;
};

/**
 * create empty touchlist with the methods
 * @constructor
 * @returns touchList
 */
function TouchList() {
	var touchList = [];

	touchList["item"] = function (index) {
		return this[index] || null;
	};

	// specified by Mozilla
	touchList["identifiedTouch"] = function (id) {
		return this[id + 1] || null;
	};

	return touchList;
}

/**
 * only trigger touches when the left mousebutton has been pressed
 * @param touchType
 * @returns {Function}
 */

var initiated = false;
function onMouse(touchType) {
	return function (ev) {
		// prevent mouse events

		if (ev.type === "mousedown") {
			initiated = true;
		}

		if (ev.type === "mouseup") {
			initiated = false;
		}

		if (ev.type === "mousemove" && !initiated) {
			return;
		}

		// The EventTarget on which the touch point started when it was first placed on the surface,
		// even if the touch point has since moved outside the interactive area of that element.
		// also, when the target doesnt exist anymore, we update it
		if (
			ev.type === "mousedown" ||
			!eventTarget ||
			(eventTarget && !eventTarget.dispatchEvent)
		) {
			eventTarget = ev.target;
		}

		triggerTouch(touchType, ev);

		// reset
		if (ev.type === "mouseup") {
			eventTarget = null;
		}
	};
}

/**
 * trigger a touch event
 * @param eventName
 * @param mouseEv
 */
function triggerTouch(eventName, mouseEv) {
	var touchEvent = document.createEvent("Event");
	touchEvent.initEvent(eventName, true, true);

	touchEvent.altKey = mouseEv.altKey;
	touchEvent.ctrlKey = mouseEv.ctrlKey;
	touchEvent.metaKey = mouseEv.metaKey;
	touchEvent.shiftKey = mouseEv.shiftKey;

	touchEvent.touches = getActiveTouches(mouseEv);
	touchEvent.targetTouches = getActiveTouches(mouseEv);
	touchEvent.changedTouches = createTouchList(mouseEv);

	eventTarget.dispatchEvent(touchEvent);
}

/**
 * create a touchList based on the mouse event
 * @param mouseEv
 * @returns {TouchList}
 */
function createTouchList(mouseEv) {
	var touchList = TouchList();
	touchList.push(new Touch(eventTarget, 1, mouseEv, 0, 0));
	return touchList;
}

/**
 * receive all active touches
 * @param mouseEv
 * @returns {TouchList}
 */
function getActiveTouches(mouseEv) {
	// empty list
	if (mouseEv.type === "mouseup") {
		return TouchList();
	}
	return createTouchList(mouseEv);
}

/**
 * TouchEmulator initializer
 */
function TouchEmulator() {
	window.addEventListener("mousedown", onMouse("touchstart"), true);
	window.addEventListener("mousemove", onMouse("touchmove"), true);
	window.addEventListener("mouseup", onMouse("touchend"), true);
}

// start distance when entering the multitouch mode
TouchEmulator["multiTouchOffset"] = 75;

if (!supportTouch) {
	new TouchEmulator();
}
